package com.ruoyi.cs.service.payment.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.Response;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.payment.*;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.utils.pay.SanjinDemoUtils;
import com.ruoyi.cs.domain.TRecharge;
import com.ruoyi.cs.domain.TUser;
import com.ruoyi.cs.domain.TUserAuthentication;
import com.ruoyi.cs.domain.pay.OrderParams;
import com.ruoyi.cs.domain.pay.Res;
import com.ruoyi.cs.mapper.TRechargeMapper;
import com.ruoyi.cs.mapper.TUserAuthenticationMapper;
import com.ruoyi.cs.mapper.TUserMapper;
import com.ruoyi.cs.service.CommonService;
import com.ruoyi.cs.service.payment.SanjinService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.*;


@Service
@SuppressWarnings("all")
@Slf4j
public class SanjinServiceImpl implements SanjinService {
    @Autowired
    private TUserMapper tUserMapper;
    @Autowired
    private CommonService commonService;
    @Autowired
    private TRechargeMapper tRechargeMapper;
    @Value("${ruoyi.sanjinNotify}")
    private String cznotify;
    @Value("${ruoyi.returnUrl}")
    private String returnUrl;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private TUserAuthenticationMapper tUserAuthenticationMapper;

    @Override
    public Response<Map> recharge(String userId, BigDecimal czMoney, String czEquipment,String czType) throws Exception {
        TUser tUser = tUserMapper.selectTUserById(userId);
        TUserAuthentication tUserAuthentication = tUserAuthenticationMapper.selectTUserAuthenticationByUserId(tUser.getUserId().toString());
        if (tUserAuthentication == null){
            /**满足触发实名认证*/
            return  Response.fail("请先实名认证！");
        }
        String out_trade_no = IdUtil.fastSimpleUUID().substring(0,30);
        log.info(""+out_trade_no.length());
        String extraAccountCertnoLastSix = tUserAuthentication.getIdcard().substring(tUserAuthentication.getIdcard().length()-6);

        BigDecimal giveFee = new BigDecimal("0");
        try {
            giveFee = commonService.rechargeVerification(tUser, czMoney);
        } catch (Exception e) {
            return Response.fail(e.getMessage());
        }
        Instant instant = Instant.now();
        Long currentTimestamp = instant.getEpochSecond();

        BigDecimal fee = czMoney.setScale(2,BigDecimal.ROUND_HALF_UP);
        Map<String, Object> map = pay(out_trade_no,fee.toString(),czType,tUserAuthentication.getRealname(),tUserAuthentication.getIdcard());
        log.info("三斤支付发起支付响应内容:{}",JSON.toJSONString(map));
        Long endTimestamp = instant.getEpochSecond();
        if(!("OK".equalsIgnoreCase(map.get("status").toString()) && "SUCCESS".equalsIgnoreCase(map.get("msg").toString()))){
            return Response.fail(map.get("msg").toString());
        }

        String url = map.get("url").toString();
        String picurl = null;
        try {
            /**生产二维码图片*/
            picurl = commonService.scQrCodeImgeWeb(url);
        } catch (Exception e) {
            log.error("yukuaiqi支付生产二维码订单异常:{}", e.getMessage());
            e.printStackTrace();
            return Response.fail("发送请求失败");
        }

        TRecharge tRecharge = new TRecharge();
        tRecharge.setUserId(userId);
        tRecharge.setCzId(out_trade_no);
        tRecharge.setDelFlag(Constants.SUCCESS);
        tRecharge.setCzType(czType);
        tRecharge.setMerchantOrderNo(out_trade_no);
        tRecharge.setPlatformOrderNo(map.get("orderid").toString());
        /**支付结果  0 待充值 1充值成功 2充值失败*/
        tRecharge.setCzStatus(Constants.CZSTATUS0);
        /**交易类型*/
        tRecharge.setCzEquipment(czEquipment);
        tRecharge.setCreateTime(DateUtils.getNowDate());
        tRecharge.setGiveFee(giveFee);
        tRecharge.setCzMoney(czMoney);
        tRecharge.setCzPlatform(Constants.CZPLATFORM8);
        tRecharge.setUserType(tUser.getUserType());
        if (StringUtils.isNotEmpty(tUser.getUserPromotersId())) {
            tRecharge.setUserPromotersId(tUser.getUserPromotersId());
        }
        int count = tRechargeMapper.insertTRecharge(tRecharge);
        if (count > 0) {
            Map resultMap = new HashMap();
            resultMap.put("picUrl", picurl);
            resultMap.put("czId", out_trade_no);
            resultMap.put("totalFee", czMoney);
            resultMap.put("url", url);
            log.info("yukuaiqi支付订单生产：参数信息：{}，支付金额：{},订单号：{}", JSON.toJSONString(tRecharge), czMoney, out_trade_no);
            return Response.success(resultMap);
        } else {
            log.error("yukuaiqi支付充值记录表插入失败：参数信息：{}，支付金额：{},订单号：{}", JSON.toJSONString(tRecharge), czMoney, out_trade_no);
            return Response.fail("充值窗口异常，请联系管理员处理!");
        }
    }

    @Override
    public String notify(HttpServletRequest request) {
        Map<String, Object> resultMap = convertRequestParametersToMap(request);
        log.info("三斤支付异步回调参数:{}",JSON.toJSONString(resultMap));

        String sign_str = "customerid=" + request.getParameter("customerid")
                + "&status=" + request.getParameter("status")
                + "&sdpayno=" + request.getParameter("sdpayno")
                + "&sdorderno=" + request.getParameter("sdorderno")
                + "&total_fee=" + request.getParameter("total_fee")
                + "&realmoney=" + request.getParameter("realmoney")
                + "&paytype=" + request.getParameter("paytype")
                + "&" + SanjinConstants.key;
        String sign = SanjinDemoUtils.encryptToMD5(sign_str);
        log.info("三斤支付支付异步通知:{},sign:{}",JSON.toJSONString(resultMap),sign_str);
        String msg = JSON.toJSONString(resultMap);
        try {
            if (sign.equals(request.getParameter("sign"))){
                String prepay_id = request.getParameter("sdpayno");
                String out_trade_no = request.getParameter("sdorderno");
                TRecharge tRecharge = tRechargeMapper.selectTRechargeById(out_trade_no);
                String platform = tRecharge == null ? "" : tRecharge.getCzPlatform();
                log.info("三斤支付回调签名认证成功");
                if (tRecharge != null) {
                    if ("1".equals(request.getParameter("status"))) {
                        if(Constants.CZSTATUS0.equals(tRecharge.getCzStatus())){
                            commonService.czSuccessHandle(tRecharge,out_trade_no, prepay_id,msg);
                        }
                    }
                    return "success";
                } else {
                    log.error("三斤支付查询充值订单信息为空,请求参数：{}", msg);
                    return "fail";
                }
            } else {
                log.info("三斤支付回调签名认证失败，signVerified=false, paramsJson:{}", msg);
                return "fail";
            }
        } catch (Exception e) {
            log.error("三斤支付回调异常,paramsJson:{},errorMsg:{}", msg, e);
            return "fail";
        }
    }

    public static Map<String, Object> convertRequestParametersToMap(HttpServletRequest request) {
        Map<String, Object> paramMap = new HashMap<>();
        // 获取所有参数名
        Enumeration<String> parameterNames = request.getParameterNames();
        // 遍历参数名并获取对应的参数值
        while (parameterNames.hasMoreElements()) {
            String paramName = parameterNames.nextElement();
            String paramValue = request.getParameter(paramName);
            paramMap.put(paramName, paramValue);
        }
        return paramMap;
    }

    public Map<String, Object> pay(String out_trade_no,String fee,String czType,String realname,String idcard){
        MultiValueMap<String,Object> map= new LinkedMultiValueMap<>();
        map.add("version", "1.0");
        map.add("customerid",SanjinConstants.customerId);
        map.add("sdorderno",out_trade_no);
        map.add("total_fee",fee);
        if(czType.equals("0")){
            map.add("paytype","weixin");
        }else {
            map.add("paytype","alipay");
        }
        map.add("bankcode",null);
        map.add("notifyurl",cznotify);
        map.add("clientip",IpUtils.getIpAddr(ServletUtils.getRequest()));
        map.add("returnurl",returnUrl);
        map.add("remark","充值");
        map.add("access_type","API");
        String signStr = SanjinDemoUtils.sortMapByValues(map.toSingleValueMap());
        String apiUrl = SanjinConstants.orderUrl;
        String userKey = SanjinConstants.key;
        String sign = SanjinDemoUtils.encryptToMD5(signStr +"&"+ userKey);
        map.add("sign",sign);
        map.add("is_jump",false);
        map.add("name",realname);
        map.add("cert_no",idcard);
        Map<String, Object> resMap = SanjinDemoUtils.postFormData(map,apiUrl);
        return resMap;
    }
}
